const obj = {
    name: 'John',
    age: 30,
    // 读书 写作 撸码 调试
    hobbies: ['reading', 'writing', 'coding', 'debugging'],
    sayHello() {
        console.log("hello");
    }
}

/* JSON转换法不支持函数 纯数据很OK */
function deepCopyByJSON(obj) {
    const jsonStr = JSON.stringify(obj)
    const objCopy = JSON.parse(jsonStr)

    return objCopy
}

/* 递归深拷贝 */
function deepCopy(data) {
    switch (true) {

        /* 对于函数 直接返回其地址 */
        case typeof (data) === "function":
            return data

        /* 基本数据类型：直接返回其本身 */
        case typeof (data) !== 'object':
            return data;

        /* 如果是数组 创建一个空数组 然后递归深拷贝每个元素 并丢入新数组 */
        case Array.isArray(data):
            // 创建新数组
            const arr = []

            data.forEach(
                item => {
                    // 递归深拷贝每个item 并将其副本丢入新数组
                    const itemCopy = deepCopy(item)
                    arr.push(itemCopy)
                }
            );
            return arr;

        /* 普通对象 创建一个空对象 然后递归深拷贝每个key-value 并丢入新对象  */
        case typeof (data) === 'object':
            // 创建新空对象 
            const copy = {}

            /* 递归深拷贝每个key-value 并丢入新对象 */
            for (let key in data) {
                const value = data[key]
                copy[key] = deepCopy(value)
            }

            // 返回该新对象
            return copy;

        default:
            return undefined;
    }
}

~function main() {
    /* JSON法对纯数据做深拷贝 */
    // const objCopy = deepCopyByJSON(obj)
    // obj.age += 1
    // obj.hobbies[1] = "写作"
    // objCopy.age += 2
    // objCopy.hobbies[2] = "撸码"
    // console.log(obj, objCopy);


    /* 递归深拷贝 */
    const objCopy = deepCopy(obj)

    obj.age += 1
    obj.hobbies[1] = "写作"

    objCopy.age += 2
    objCopy.hobbies[2] = "撸码"

    // 给副本的函数重新赋值新地址 并不会影响本体
    objCopy.sayHello = () => console.log("雷猴");

    console.log(obj, objCopy);
    obj.sayHello()
    objCopy.sayHello()
}()